/*
 * File:   Ecosystem.h
 * Author: Administrateur
 *
 * Created on 4 novembre 2008, 18:53
 */

#ifndef _ECOSYSTEM_H
#define	_ECOSYSTEM_H

#include<iostream>
#include<vector>
#include"Animal.h"
#include"Vegetal.h"
#include"Entity.h"
#include"MapPredator.hpp"
#include"TypeEntity.h"

using namespace std;

class Animal;
class Vegetal;

class Ecosystem {
public:

    /**
     * Constructor
     */
    Ecosystem(int const& _length, int const& _width);

    /**
     *  Check if there is an entity at the position given in parameter
     *
     *  @param x position X
     *  @param y position Y
     *  @return true if there is an entity at the position (x,y). False otherwise.
     */
    bool Ecosystem::isAvailable(int const& x, int const& y) const;

    /**
     * Getter for the length of the grid
     *
     * @return Length of the grid
     */
    int l() const {
        return length;
    }

    /**
     * Getter for the width of the grid
     *
     * @return Width of the grid
     */
    int w() const {
        return width;
    }

    /**
     *  Getter for the map Predator --> Preys
     *
     *  @return const ref of the map Predator --> Preys
     */
    MapPredator const& mapPredator() const {
        return mp;
    }

    /**
     *  Display the system with all entities
     **/
    void displaySystem() const;

    /**
     * Start the ecosystem
     */
    void start() const;

    /**
     * Getter for the entity at the position (x, y)
     *
     * @param x - Position X of the entity
     * @param y - Position Y of the entity
     *
     * @return Entity at the position (x, y)
     */
    Entity * getEntityAt(int x, int y) const ;

    /**
     * Getter for the entities around the position (x, y).
     *
     * @param x - Position X
     * @param y - Position Y
     * @param fov - Field of view
     *
     * @return Vector of the entities around the position (x, y)
     */
    vector<Entity*> getEntitiesAt(int x, int y, int fov) const ;

    /**
     *  Kill an entity of type <i>type</i> at the position (x, y)
     *
     *  @param x    - Position X of the entity to kill
     *  @param y    - Position Y of the entity to kill
     *  @param type - Type of the entity to kill (ANIMAL or VEGETAL)
     **/
    void killEntityAt(int x, int y, TypeEntity type);

    /**
     * Create animals configured in the config file <i>configName</i>.
     * This config file contains:
     * 		- Type: Type of the animal
     * 		- Quantity: Quantity of the animal <i>type</i> to create
     * 		- PEscape: Percentage to escape during its turn
     * 		- PMove: Percentage to move during its turn
     * 		- PReproduce: Percentage to reproduce during its turn
     * 		- Tokens: Number of tokens
     * 		- MaxLife: Maximum lifepoint of the animal
     * 		- Fov: Field of view of the animal
     *
     * @param configName - Path of the config file
     */
    void loadAnimals(char const* configName);

    /**
     * Create vegetals configured in the config file <i>configName</i>.
     * This config file contains:
     * 		- Type: Type of the animal
     * 		- Quantity: Quantity of the animal <i>type</i> to create
     * 		- Expension: Factor of expension when it
     *
     * @param configName - Path of the config file
     */
    void loadVegetals(char const* configName);

    /**
     * Configure the map Predator --> vector of Preys
     * Syntax of the file:
     * 		[PREDATOR_NAME]
     * 		Prey1 = PREY_NAME_1
     * 		Prey2 = PREY_NAME_2
     * 		Prey3 = PREY_NAME_3
     * 		...
     *
     * @param configName - Path of the config file
     */
    void loadPredators(char const* configName);

    /**
     * Generate random coordinates.
     */
    Position randomResource() const;

    /** 
     *  Add an animal to the ecosystem
     *
     *  @param pos          - Position of the animal
     *  @param race         - Race of the animal
     *  @param pEscape      - Percentage to escape during its turn
     *  @param pMove        - Percentage to move during its turn
     *  @param pReproduce   - Percentage to reproduce during its turn
     *  @param tokens       - Number of tokens
     *  @param maxLife      - Maximum lifepoint of the animal
     * 	@param fov          - Field of view of the animal
     *
     **/
    void addAnimal(string race, float pEscape, float pMove, float pReproduce, int tokens, int maxLife, int fov);

    /**
     *  Add a vegetal to the ecosystem
     *
     *  @param pos              - Position of the vegetal
     *  @param race             - Race of the vegetal
     *  @param expension_factor - Factor of expension
     **/
    void addVegetal(string race, int expension_factor);

    /**
     *  Unit test for the Map predator.
     *  It adds the parameter pred as a predator and prey as a prey of the predator.
     *  Then, it tests if the pred is really identified as a predator for the prey.
     *
     *  @param pred - The predator to add
     *  @param prey - The prey to add
     *
     *  @return true if the test passed. False otherwise.
     **/
    bool test_isPredator(string const& pred, string const& prey);

/**
 *  Unit test for the method getEntityAt.
 *  It adds a vegetal at the position (x, y) and try to find it at this position.
 *
 *  @param x - Position X of the vegetal to add and test if it exists
 *  @param y - Position Y of the vegetal to add and test if it exists
 *
 *  @return true if the vegetal exists at the position (x, y) after it was inserted. False otherwise.
 **/
bool Ecosystem::test_getEntityAt(int x, int y);

private:
    int                 length;
    int 		width;
    vector<Animal*> 	vect_animal;
    vector<Vegetal*> 	vect_vegetal;
    MapPredator         mp;
};

#endif	/* _ECOSYSTEM_H */

